import { type MaybeElementRef, onClickOutside } from '@vueuse/core'
import { ref, type Ref } from 'vue'
import { Connection } from '@jsplumb/browser-ui'
import { useDataFlowState } from '@/model/data-flow/data-flow-state'

export interface NodeOperation {
  delete: () => void
  edit: () => void
  copy: () => void
}

export interface ConnectorOperation {
  delete: () => void
}

export interface OperationSpaceOperation {
  paste: () => void
}

export type ContextmenuType = 'operation-space' | 'connector' | 'node'

export function useContextMenu(target: MaybeElementRef, container: Ref, viewBox: Ref) {
  const contextmenu: Ref<{
    show: boolean
    payload?: any
    event?: PointerEvent
    type: ContextmenuType
    left: number
    top: number
  }> = ref({
    show: false,
    type: 'operation-space',
    left: 0,
    top: 0
  })

  onClickOutside(target, () => {
    contextmenu.value.show = false
  })

  const { dataFlowState } = useDataFlowState()

  const calculateLocation = (event: PointerEvent) => {
    event.preventDefault()
    contextmenu.value.event = event
    const rect = container.value.getBoundingClientRect()
    const viewBoxRect = viewBox.value.getBoundingClientRect()
    const contextmenuWidth = 205
    const contextmenuHeight = 100
    if (event.clientX + contextmenuWidth >= viewBoxRect.left + viewBoxRect.width) {
      contextmenu.value.left = viewBoxRect.left + viewBoxRect.width - contextmenuWidth - rect.left
    } else {
      contextmenu.value.left = event.clientX - rect.left
    }
    if (event.clientY + contextmenuHeight >= viewBoxRect.top + viewBoxRect.height) {
      contextmenu.value.top = viewBoxRect.top + viewBoxRect.height - contextmenuHeight - rect.top
    } else {
      contextmenu.value.top = event.clientY - rect.top
    }
    contextmenu.value.show = true
  }

  const showOperationSpaceContextmenu = (event: PointerEvent) => {
    //跟画布相关的操作
    contextmenu.value.type = 'operation-space'
    calculateLocation(event)
    dataFlowState.clearSelectedNode()
  }

  const showConnectorContextmenu = (connection: Connection, event: PointerEvent) => {
    //跟连线相关的操作
    contextmenu.value.type = 'connector'
    contextmenu.value.payload = connection
    calculateLocation(event)
    dataFlowState.clearSelectedNode()
  }

  const showNodeContextmenu = (element: HTMLElement, event: PointerEvent) => {
    //跟节点相关的操作
    contextmenu.value.type = 'node'
    contextmenu.value.payload = element
    calculateLocation(event)
  }

  return {
    contextmenu,
    showOperationSpaceContextmenu,
    showConnectorContextmenu,
    showNodeContextmenu
  }
}
